﻿using WcfGeebaServer.Users;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using WcfGeebaServer.Policies;
using WcfGeebaServer.ContentManage;
using WcfGeebaServer.DBDAL;

namespace TestGeeba
{
    
    
    /// <summary>
    ///This is a test class for UserTest and is intended
    ///to contain all UserTest Unit Tests
    ///</summary>
    [TestClass()]
    public class GPolicyTest
    {
        GForum forum;
        GPolicy policy;

        public GPolicyTest()
        {
            Data.ClearDB();
            forum = GForum.GetForum();
            forum.init(new Member("boris", "1234", true), new GPolicy());
            policy = forum.Policy;
            /*Data.subForums.Clear();
            Data.subForumsThreads.Clear();
            Data.moderators.Clear();*/

        }


        private TestContext testContextInstance1;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance1;
            }
            set
            {
                testContextInstance1 = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestMethod()]
        public void CanEditThread()
        {
            Member m1 = new Member("dude1", "1234", true);
            Member m2 = new Member("dude2", "1234", true);
            GThread thread = new GThread("bla", "bla", m1);
            Assert.IsTrue(policy.CanEditThread(thread, m1));
            Assert.IsFalse(policy.CanEditThread(thread, m2));
        }

        [TestMethod()]
        public void CanDeleteThread()
        {
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");
            Member m3 = new Member("dude3", "1234", true);
            forum.register("dude3", "1234");
            forum.addSubForum("bla", m2);
            GSubForum sf = forum.getSubForum("bla");
            GThread thread = new GThread("bla", "bla", m1);
            Assert.IsTrue(policy.CanDeleteThread(thread, m1, sf));
            Assert.IsTrue(policy.CanDeleteThread(thread, m2, sf));
            Assert.IsTrue(policy.CanDeleteThread(thread, forum.Admin, sf));
            Assert.IsFalse(policy.CanDeleteThread(thread, m3, sf));
        }

        [TestMethod()]
        public void CanAddModerator()
        {
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");
            forum.addSubForum("addModeratorSF", m1);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            for (int i = 0; i < 5; i++)
            {
                Assert.IsFalse(policy.CanAddModerator(m2, sf));
                sf.publish(new GThread("a", "b", m2));
            }
            Assert.IsTrue(policy.CanAddModerator(m2, sf));
        }

        [TestMethod()]
        public void CanRemoveModerator()
        {
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");
            forum.addSubForum("addModeratorSF", m1);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            for (int i = 0; i < 5; i++)
            {
                sf.publish(new GThread("a", "b", m2));
            }
            Assert.IsFalse(policy.CanRemoveModerator(m1, sf));
            sf.addMemberAsModerator(m2);
            Assert.IsTrue(policy.CanRemoveModerator(m1, sf));
            Assert.IsFalse(policy.CanRemoveModerator(m2, sf));
            sf.removeMemberFromModerators(m1);
            Assert.IsFalse(policy.CanRemoveModerator(m2, sf));
        }

        [TestMethod()]
        public void CanReplaceModerator()
        {
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");
            forum.addSubForum("addModeratorSF", m1);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            Assert.IsFalse(policy.CanReplaceModerator(m1, m2, sf));
            for (int i = 0; i < 5; i++)
            {
                sf.publish(new GThread("a", "b", m2));
            }
            Assert.IsTrue(policy.CanReplaceModerator(m1, m2, sf));
        }

        [TestMethod()]
        public void CanPublishMessage()
        {
            Member m1 = new Member("dude1", "1234", false);
            forum.addSubForum("addModeratorSF", m1);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            GThread thread = new GThread("bka","bla",m1);
            //not a member
            Assert.IsFalse(policy.CanPublishMessage(m1,sf,thread));
            
            //not active
            forum.register("dude1", "1234");
            Assert.IsFalse(policy.CanPublishMessage(m1, sf, thread));

            m1.setIsActive(true);
            Assert.IsTrue(policy.CanPublishMessage(m1, sf, thread));

        }

        [TestMethod()]
        public void CanBanMember()
        {
            Member m0 = new Member("dude0", "1234", true);
            forum.register("dude0", "1234");
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");

            //setting m2 as LawBreaker (publish while not active)
            m2.setIsActive(false);
            forum.addSubForum("addModeratorSF", m0);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            GThread thread = new GThread("bka", "bla", m2);
            sf.publish(thread);

            //requesting is not Admin/Moderator
            Assert.IsFalse(policy.CanBanMember(m1, m2));

            //m1 is not LawBreaker
            Assert.IsFalse(policy.CanBanMember(m0, m1));

            Assert.IsTrue(policy.CanBanMember(m0, m2));
        }

        [TestMethod()]
        public void IsNotification()
        {
            Member m1 = new Member("dude1", "1234", true);
            forum.register("dude1", "1234");
            Member m2 = new Member("dude2", "1234", true);
            forum.register("dude2", "1234");
            Member m3 = new Member("dude3", "1234", true);
            forum.register("dude3", "1234");
            forum.addSubForum("addModeratorSF", m1);
            GSubForum sf = forum.getSubForum("addModeratorSF");
            GThread thread = new GThread("bka", "bla", m1);
            GThread thread2 = new GThread("bka", "bla", m2);
            int id1 = sf.publish(thread);
            int id2 = sf.publish(thread2);
            thread = new GThread(id1, thread);
            thread2 = new GThread(id2, thread2);

            Assert.IsFalse(policy.IsNotification(m3, thread));
            
            Assert.IsTrue(policy.IsNotification(m1, thread2));
            Assert.IsTrue(policy.IsNotification(m2, thread));
            Assert.IsFalse(policy.IsNotification(m1, thread));


            GPost post = new GPost("subj", "cont", m3, thread);
            int pid = thread.addPost(post);
            post = new GPost(pid, post);

            Assert.IsTrue(policy.IsNotification(m1, post));
            Assert.IsTrue(policy.IsNotification(m2, post));



        }

        [TestMethod()]
        public void CanSubscribe()
        {
            Member m1 = new Member("dude1", "1234", true);
            Assert.IsTrue(policy.CanSubscribe(m1.Username));

            forum.register("dude1", "1234");
            m1.setIsActive(false);
            Assert.IsFalse(policy.CanSubscribe(m1.Username));

            m1.setIsActive(true);
            Assert.IsTrue(policy.CanSubscribe(m1.Username));
            
        }
    }

}
